---
title: "App Model"
description: "Third-party application data model"
---

## Overview

The App model represents third-party applications (TPAs) in the MentraOS ecosystem. It stores app metadata, authentication credentials, webhook configurations, and app store status.

## Location

`packages/cloud/src/models/app.model.ts`

## Schema Structure

### Core Fields

```typescript
{
  // Identity
  packageName: string,              // Unique identifier (e.g., "com.translator.app")
  name: string,                     // Display name
  description: string,              // App description
  version: string,                  // Semantic version
  type: AppType,                    // 'AGENT' | 'UI' | 'HARDWARE'
  
  // Authentication
  hashedApiKey: string,             // Hashed API key for authentication
  hashedEndpointSecret?: string,    // Optional webhook secret
  
  // Store Management
  appStoreStatus: AppStoreStatus,   // Development/Published status
  isPublic: boolean,                // Publicly available flag
  reviewNotes?: string,             // Review process notes
  reviewedBy?: string,              // Reviewer identifier
  reviewedAt?: Date,                // Review timestamp
  
  // Organization
  organizationId?: ObjectId,        // Owning organization
  
  // Configuration
  settings?: AppSetting[],          // Available settings
  permissions?: Permission[],       // Required permissions
  tools?: ToolSchema[],            // AI tool definitions
  webhooks?: WebhookConfig,        // Webhook endpoints
  hardware?: HardwareRequirement[], // Hardware requirements
  
  // Metadata
  logo?: string,                    // App logo URL
  smallLogo?: string,              // Small logo variant
  bannerImage?: string,            // Store banner image
  screenshots?: string[],          // App screenshots
  demoVideoUrl?: string,           // Demo video
  supportUrl?: string,             // Support contact
  documentationUrl?: string,       // Documentation link
  websiteUrl?: string,             // Marketing website
  privacyPolicyUrl?: string,       // Privacy policy
  termsOfServiceUrl?: string,      // Terms of service
  
  // Analytics
  installCount?: number,           // Total installations
  activeUsers?: number,            // Active user count
  rating?: number,                 // Average rating
  featured?: boolean,              // Featured app flag
  
  // Timestamps
  createdAt: Date,
  updatedAt: Date
}
```

### App Types

```typescript
enum AppType {
  AGENT = 'AGENT',      // AI-powered apps
  UI = 'UI',           // Visual interface apps
  HARDWARE = 'HARDWARE' // Hardware integration apps
}
```

### App Store Status

```typescript
type AppStoreStatus = 
  | 'DEVELOPMENT'    // In development, not public
  | 'SUBMITTED'      // Submitted for review
  | 'REJECTED'       // Failed review
  | 'PUBLISHED'      // Available in store
```

### Settings Configuration

Apps can define user-configurable settings:

```typescript
settings: [{
  key: string,                    // Setting identifier
  type: AppSettingType,          // STRING | NUMBER | BOOLEAN | SELECT
  label: string,                 // Display label
  description?: string,          // Help text
  defaultValue?: any,           // Default value
  required?: boolean,           // Required flag
  options?: Array<{             // For SELECT type
    label: string,
    value: string
  }>,
  min?: number,                 // For NUMBER type
  max?: number,
  step?: number
}]
```

### Permission Declarations

Apps must declare required permissions:

```typescript
permissions: [{
  type: PermissionType,         // Permission category
  reason: string,               // Why it's needed
  required: boolean,            // Required vs optional
  settings?: any               // Permission-specific config
}]
```

Permission types include:
- `TRANSCRIPTION`: Access to speech-to-text
- `AUDIO`: Access to audio stream
- `CAMERA`: Camera/photo access
- `LOCATION`: Location data
- `NOTIFICATIONS`: Phone notifications
- `DISPLAY`: Screen output
- `STORAGE`: Persistent storage

### Hardware Requirements

Apps can specify hardware needs:

```typescript
hardware: [{
  type: HardwareType,                    // DISPLAY | CAMERA | etc.
  level: HardwareRequirementLevel,       // REQUIRED | OPTIONAL
  minVersion?: string,                   // Minimum version
  features?: string[]                    // Specific features
}]
```

### Webhook Configuration

```typescript
webhooks: {
  start?: {
    url: string,                        // Webhook URL
    headers?: Record<string, string>,   // Custom headers
    timeout?: number                    // Timeout in ms
  },
  stop?: { /* same structure */ },
  toolCall?: { /* same structure */ }
}
```

### Tool Schemas

For AI-powered apps:

```typescript
tools: [{
  name: string,                         // Tool identifier
  description: string,                  // What it does
  inputSchema: {                        // JSON Schema
    type: 'object',
    properties: { /* ... */ },
    required: string[]
  },
  outputSchema?: { /* ... */ }          // Expected output
}]
```

## Indexes

- **packageName**: Unique index
- **organizationId**: For org queries
- **appStoreStatus**: For store filtering
- **type**: For category queries
- **featured**: For featured apps

## Methods

### Instance Methods

The App model primarily uses standard Mongoose methods:

```typescript
// Find app
const app = await App.findOne({ packageName: 'com.translator.app' });

// Update app
app.version = '1.2.0';
await app.save();

// Soft delete
app.isPublic = false;
app.appStoreStatus = 'DEVELOPMENT';
await app.save();
```

### Static Methods

```typescript
// Find all published apps
const publishedApps = await App.find({ 
  appStoreStatus: 'PUBLISHED',
  isPublic: true 
});

// Find organization apps
const orgApps = await App.find({ 
  organizationId: orgId 
});
```

## Security

### API Key Management
- API keys are hashed using SHA-256
- Never store or transmit plain text keys
- Keys are generated using crypto-random

### Webhook Security
- Optional endpoint secrets for verification
- HMAC signatures for webhook payloads
- Timeout limits to prevent hanging

## App Lifecycle

### Development Flow
1. **DEVELOPMENT**: App created, private to developer
2. **SUBMITTED**: Submitted for review
3. **REJECTED**: Failed review (with notes)
4. **PUBLISHED**: Available in public store

### Review Process
```typescript
// Submit for review
app.appStoreStatus = 'SUBMITTED';
app.reviewNotes = 'Ready for review';
await app.save();

// Review decision
app.appStoreStatus = 'PUBLISHED';
app.reviewedBy = 'reviewer@mentraos.com';
app.reviewedAt = new Date();
await app.save();
```

## Best Practices

1. **Validate package names** - Use reverse domain notation
2. **Version semantically** - Follow semver (1.0.0)
3. **Declare all permissions** - Be transparent
4. **Provide documentation** - Help users understand
5. **Test webhooks** - Ensure they're responsive
6. **Handle errors gracefully** - Don't crash user sessions

## Example Usage

### Creating an App

```typescript
const app = new App({
  packageName: 'com.example.translator',
  name: 'Universal Translator',
  description: 'Real-time translation for smart glasses',
  version: '1.0.0',
  type: 'UI',
  
  // Organization
  organizationId: orgId,
  
  // Settings
  settings: [
    {
      key: 'targetLanguage',
      type: 'SELECT',
      label: 'Target Language',
      defaultValue: 'es',
      options: [
        { label: 'Spanish', value: 'es' },
        { label: 'French', value: 'fr' }
      ]
    }
  ],
  
  // Permissions
  permissions: [
    {
      type: 'TRANSCRIPTION',
      reason: 'To capture speech for translation',
      required: true
    },
    {
      type: 'DISPLAY',
      reason: 'To show translations',
      required: true
    }
  ],
  
  // Webhooks
  webhooks: {
    start: {
      url: 'https://api.example.com/webhook/start',
      headers: { 'X-API-Key': 'webhook-key' }
    }
  },
  
  // Store info
  appStoreStatus: 'DEVELOPMENT',
  isPublic: false,
  logo: 'https://example.com/logo.png',
  supportUrl: 'support@example.com'
});

// Hash the API key before saving
app.hashedApiKey = hashApiKey('app_secret_key');
await app.save();
```

### Finding Apps for User

```typescript
// Get user's installed apps
const user = await User.findOne({ email: 'user@example.com' });
const installedPackageNames = user.installedApps.map(a => a.packageName);

// Find app details
const apps = await App.find({
  packageName: { $in: installedPackageNames },
  appStoreStatus: 'PUBLISHED'
}).lean();
```